package online.inote.dic.validator.core.aspects;

import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;

import online.inote.dic.common.annotions.Valid;
import online.inote.dic.common.utils.ResultFactory;

/**
 * <p>
 * Desc: 参数校验切面
 * </p>
 *
 * @author XQF SUI
 * @created 2018年9月10日 上午10:49:20
 * @version 1.0
 */
@Order
@Aspect
@Component
public class ValidAspect {
	
	private Logger logger = LoggerFactory.getLogger(getClass());
	
	@Around(value = "@annotation(valid)")
	public Object aroundValids(ProceedingJoinPoint point, Valid valid) {
		
		try {
			Object[] args = point.getArgs();
			
			logger.info("调用接口:[ {} ]开始，入参信息:[ {} ]，开始参数校验", point.getSignature().toString(), JSON.toJSONString(point.getArgs()));
			
			if (args == null) {
				return failResult(point, "校验参数时，入参不能为空");
			}
			
			String method = valid.method();
			Class<?>[] paramType = valid.paramType();
			
			if (StringUtils.isBlank(method)) {
				method = point.getSignature().getName();
			}
			
			if (paramType.length == 0) {
				int i = 0;
				paramType = new Class<?>[args.length];
				
				for (Object clazz : args) {
					paramType[i++] = clazz.getClass();
				}
			}
			
			Object invokeResult = valid.validator().getMethod(method, paramType).invoke(valid.validator().newInstance(), args[0]);
			
			logger.info("校验结果：" + JSON.toJSONString(invokeResult));
			
			if (!validResultHandle(invokeResult)) {
				return invokeResult;
			}
			
			return point.proceed();
		} catch (Throwable e) {
			logger.error("调用方法失败", e);
			return failResult(point, "系统错误");
		}
	}
	
	/**
	 * @description 验证结果处理
	 * @author XQF.Sui
	 * @created 2019年6月22日 下午11:55:46
	 * @param invokeResult
	 * @return
	 */
	private boolean validResultHandle(Object invokeResult) {
		if (invokeResult == null) {
			return false;
		}
		
		@SuppressWarnings("unchecked")
		ResultFactory<Object> result = (ResultFactory<Object>) invokeResult;
		
		return result.isSuccess();
	}
	
	/**
	 * <p>
	 * Desc: 返回结果(目前项目只有返回Map和String, 如以后有添加其他类型返回值, 需在此处增加类型处理, 以便于更好的前端交互)
	 * </p>
	 *
	 * @author XQF SUI
	 * @created 2018年1月3日 下午5:51:04
	 * @param point
	 * @param resultEnum
	 * @return
	 */
	public Object failResult(ProceedingJoinPoint point, String message) {
		Class<?> returnType = ((MethodSignature) point.getSignature()).getReturnType(); 
		
		if (returnType == ResultFactory.class) {
			return ResultFactory.fail(message);
		} else if (returnType == Map.class) {
			return ResultFactory.fail(message).toJSONObject();
		}
		
		return ResultFactory.fail(message).toJSON();
	}
}